/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package interfaz;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 *
 * Esta clase es la encargada de encontrar los patrones, segun las reglas 
 * especificadas para cada uno de ellos.
 * @author Emmanuel
 */
public class Patrones {
    
    private Clase c;
    private HashSet<ArrayList<String>> dosMas;
    private HashSet<ArrayList<String>> soloUno;    
    private HashSet<ArrayList<String>> todos;
    private HashSet<String> solitarias;
    
    public Patrones(){
        
        dosMas = new HashSet();
        soloUno = new HashSet();
        todos = new HashSet();
        solitarias = new HashSet();
        c = new Clase();
    }
    
    
    public Object[] buscar(String patron){
        
        Object[] p  = null;
        ArrayList<ArrayList<String>> interfaz = new ArrayList();
        switch(patron){
            
            case "Abstract Factory":
                
                float porcentaje = 0;
                HashSet<ArrayList<String>> posiblesFabricas = new HashSet();
                HashSet<ArrayList<String>> asociados = new HashSet();
                HashMap<ArrayList<String>, Integer> mapa = new HashMap();
                /*
                * Solo las estructuras (conjunto de clases que extienden en las que
                * hay relacion de generalizacion - realizacion) en las que entre ella
                * haya asociacion, 3 (o mas) estructuras conectadas entre si.
                */
                boolean hay = false;
                for(ArrayList<String> ar: dosMas){
                for(ArrayList<String> ar2: dosMas){
                    hay = false;
                    if(!ar.equals(ar2)){
                        for(String s1: ar){
                            for(String s2: ar2){
                                
                                if(!s1.equals(s2)){
                                    
                                    if(c.hayAsociacion(s1, s2)){
                                        hay = true;
                                              
                                                posiblesFabricas.add(ar);
                                                asociados.add(ar2);

                                        }
                                    }
                                }
                            }
                        }
                    
                    int cuantos = 0;
                    try{
                        cuantos = mapa.get(ar);
                    }
                    catch(Exception e){
                        cuantos = 0;
                    }
                    
                    if(hay)
                        mapa.put(ar, cuantos+1);
                    
                    }
                }

                for(ArrayList<String> valor: mapa.keySet()){
                    if(mapa.get(valor) < 2)
                        posiblesFabricas.remove(valor);
                }
                
                
                /*
                 * En este punto ya se obtuvo el 50% del patron
                 */
                porcentaje = 50;
                /*
                 * Ahora a buscar, mas especifico, que se cumplan
                 * con la estructura exacta o parecida. Se empieza desde
                 * el indice 1, pues segun fabrica abstracta, las superclases
                 * de cada estructura no tienen asociacion mas que con el
                 * cliente.
                 */
                
               
                    
                mapa = new HashMap();
                short total = 0;
                for(ArrayList<String> pf: posiblesFabricas){
                    
                    for(ArrayList<String> as: asociados){
                        
                        if(!pf.equals(as)){
                        for(int i = 1; i < pf.size(); i++){
                            for(int j = 1; j < as.size(); j++){
                                if(c.hayAsociacion(pf.get(i), as.get(j))){
                                    
                                    total++;
                                    
                                }
                            }
                            
                            
                         }
                       
                        if(total > (as.size() - 1)){
                            // A partir de aqui para el porcentaje
                            porcentaje = 70;
                            
                        for(Class clase1: c.getClases()){
                            if(c.hayAsociacion(clase1.getSimpleName(), pf.get(0))
                                    &&
                               c.hayAsociacion(clase1.getSimpleName(), as.get(0))){
                                //Significa que hay algun CLIENTE
                                porcentaje = 75;
                            }
                                
                        }
                            
                       
                           ArrayList<String> paraInterfaz = new ArrayList(pf);
                           paraInterfaz.addAll(as);
                           interfaz.add(paraInterfaz);
                           
                           
                            ArrayList<String> unido = new ArrayList();
                            
                            
                            unido.add("Fabrica Abstracta: " + pf + "\n Familia Productos: " + as );
                            //unido.addAll(as);
                            mapa.put(unido, (int)(porcentaje));
//                            
//                            posiblesFabricasRefinado.add(unido);
                            
                        }
                        total = 0;
                    }
                  }
                }
                
                

                ArrayList<String> nuevo = new ArrayList();
                for(ArrayList<String> i: mapa.keySet()){
                    nuevo.add(i + "["+mapa.get(i)+"%]\n\n");
                    
                }

                p = nuevo.toArray();
                
                break;
                
                
            case "Bridge":
                
                mapa = new HashMap();
                interfaz = new ArrayList();
                for(ArrayList<String> ar: todos){
                    for(ArrayList<String> ar2: todos){
                        /*
                         * en este patron, se requiere que 2 estructuras
                         * esten conectadas entre si con una relacion de asociacion
                         * pero que esta relacion sea entre la superclase comun
                         * de cada una de esas estructuras, por lo tanto, nomas
                         * se verificara el indice 0 de cada estructura.
                         */
                        float probabilidad = 0;
                        if(!ar.equals(ar2)){
                            if(c.tieneUn(ar.get(0), ar2.get(0))){
                                probabilidad = 50;
                                
                                for(int i = 1; i < ar.size(); i++){
                                    if(c.hayAsociacion(ar.get(i), ar2.get(0))){
                                       probabilidad = 70;
                                    }
                                }
                                if(probabilidad >= 70){
                                    
                                    if(c.esInterfaz(ar.get(0)) && c.esInterfaz(ar2.get(0)))
                                        probabilidad += 10;
                                    
                                    ArrayList<String> paraInterfaz = new ArrayList(ar);
                                    paraInterfaz.addAll(ar2);
                                    interfaz.add(paraInterfaz);
                                    
                                    ArrayList<String> union = new ArrayList();
                                    union.add("Puente: " +ar + "\nUnion: " + ar2 );
                                    mapa.put(union, (int) probabilidad);
                                    
                                    
                                }
                            }
                        }  
                    }
                }    
                
                nuevo = new ArrayList();
                for(ArrayList<String> i: mapa.keySet()){
                    nuevo.add(i + "["+mapa.get(i)+"%]\n");
                }
                p = nuevo.toArray();
                
                break;
                
            case "Singleton":
                
                ArrayList<String> singletones = new ArrayList();
                //Singleton es el unico que se presenta en una sola clase
                for(Class clase: c.getClases()){
//                    
                    if(
                       c.constructorPrivado(clase.getSimpleName()) 
                       &&
                       c.algunMetodoDevuelve(clase.getSimpleName(), clase.getSimpleName()))
                      {
                        
                        singletones.add(clase.getSimpleName());
                    }
                    
                }
                
                p = singletones.toArray();
                break;
                
            case "Builder":
                
                HashSet<ArrayList<String>> posiblesBuilderAux = new HashSet();
                //Usado para las relaciones entre la estructura y el producto
                HashMap<ArrayList<String>, Class> mapaEstructura_Producto = new HashMap();
                
                //Igual que el de arriba pero para el director
                HashMap<ArrayList<String>, Class> mapaEstructura_Director = new HashMap();
                mapa = new HashMap();                
               
                for(Class clase: c.getClases()){      
                    for(ArrayList<String> ar: todos){
                        int totales = (ar.size()-1);
                        int cuento = 0;
                        /*
                         * Busca que en las subclases de la estructura 
                         * haya relaciones de asociacion con otra clase del
                         * arreglo de todas las clases
                         */
                        for(int i = 1; i < ar.size(); i++){
                            if(!ar.get(i).equals(clase.getSimpleName()) &&
                              c.hayAsociacion(ar.get(i),clase.getSimpleName())){
                                cuento++;
                            } 
                        }
                        /*
                         * Si hay asociacion de todas las clases con una sola
                         * entonces se añade a la relacion estructura - producto
                         * y al mapa que tiene cuantas veces esa estructura
                         * se le han encontrado relaciones con otra clase,
                         * esto se hace porque es necesario que nada mas por cada
                         * estructura se tenga una relacion de asociacion de todas
                         * sus sublaces con una y solo una clase, que representa
                         * al producto.
                         */
                        if(cuento == totales){
                            mapaEstructura_Producto.put(ar, clase);
                            int cuantos = 0;
                                try{
                                    cuantos = mapa.get(ar);
                                }
                                catch(Exception e){
                                    cuantos = 0;
                                }
                                mapa.put(ar, cuantos+1);
                                
                        }
                        
                         
                    }
                }
                HashMap<ArrayList<String>,Integer> segundoMapa = new HashMap();
                for(ArrayList<String> i: mapa.keySet()){
                    if(mapa.get(i) == 1){
                        //Significa que todas las clases "hijo" de la
                            //jerarquia tienen asociacion con otra clase, es
                            //decir el producto.
                        //el map segundoMapa maneja el porcentaje de parecido 
                        segundoMapa.put(i, 70);//70 por ciento
                            posiblesBuilderAux.add(i);
                    }
                    
                }

                for(Class cl: c.getClases()){
                    for(ArrayList<String> m: posiblesBuilderAux){
                        if(c.hayAsociacion(cl.getSimpleName(), m.get(0))
                                &&
                           c.hayAsociacion(cl.getSimpleName(), 
                                mapaEstructura_Producto.get(m).getSimpleName())){
                            //m.add(cl.getSimpleName());
                            segundoMapa.put(m, 90);
                            mapaEstructura_Director.put(m, cl);
                        }

                    }
                }
                
                nuevo = new ArrayList();
                for(ArrayList<String> i: mapa.keySet()){
                    
                    ArrayList<String> paraInterfaz = new ArrayList();
                           
                    if(segundoMapa.get(i) != null && mapaEstructura_Director.get(i) != null){
                        nuevo.add("Director: [" + mapaEstructura_Director.get(i).getSimpleName()
                                + "] Producto: [" + mapaEstructura_Producto.get(i).getSimpleName()
                                + "] Builder: " + i + " [" + segundoMapa.get(i) + "%]\n");
                        paraInterfaz.add(mapaEstructura_Director.get(i).getSimpleName());
                        paraInterfaz.add(mapaEstructura_Producto.get(i).getSimpleName());
                        paraInterfaz.addAll(i);
                        
                        
                       // nuevo.add(i + "["+segundoMapa.get(i)+"%]");
                    }
                    if(segundoMapa.get(i) != null && mapaEstructura_Director.get(i) == null){
                        nuevo.add("Director: [" + "N/A"
                                + "] Producto: [" + mapaEstructura_Producto.get(i).getSimpleName()
                                + "] Builder: " + i + " [" + segundoMapa.get(i) + "%]\n");
                        
                        paraInterfaz.add(mapaEstructura_Producto.get(i).getSimpleName());
                        paraInterfaz.addAll(i);
                       // nuevo.add(i + "["+segundoMapa.get(i)+"%]");
                    }
                   
                    interfaz.add(paraInterfaz);
                }
                
                            
                p = nuevo.toArray();
                
                break;
                
            case "Factory Method":
                
                int contador = 0;
                
                HashSet<ArrayList<String>> factorys = new HashSet();
                porcentaje = 0;
                for(ArrayList<String> ar : todos){
                    for(ArrayList<String> ar2: todos){
                        if(c.hayAsociacion(ar.get(0), ar2.get(0)) && !ar.equals(ar2)
                                && c.esInterfaz(ar.get(0)) && c.esInterfaz(ar2.get(0))
                                && ar.size() == ar2.size()){
                            // 70% pues la estructura y el numero de clases
                            //en este patron es muy precisa
                            porcentaje = 70;
                            //System.out.println(ar + " -> " + ar2);
                            
                            for(int i = 1; i < ar.size(); i++){
                                for(int j = 1; j < ar2.size(); j++){
                                    if(c.hayAsociacion(ar.get(i), ar2.get(j), true)){
//                                        System.out.println(ar.get(i) + ":" + ar2.get(j));
                                        contador++;
                                    }
                                }
                            }
                            
                            if(ar.size() - 1 == contador){
                                ArrayList<String> paraInterfaz = new ArrayList(ar);
                                paraInterfaz.addAll(ar2);
                                interfaz.add(paraInterfaz);
                                
                                porcentaje = 90;
                                ArrayList<String> union = new ArrayList();
                                
                                union.add("Factory: " + ar + " Producto: " + ar2 + "[" + porcentaje + "]");
                                factorys.add(union);
                            }
                            contador = 0;
                        }
                           
                        
                        
                    }
                }
                
                p = factorys.toArray();
                
                break;
                
            case "Prototype":
                
                /*
                 * Java en su API tiene soporte para este patron, como
                 * esta herramienta esta hecha para este lenguaje, se buscara
                 * la implementacion con las clases del API ya existentes.
                 */
                ArrayList<ArrayList<String>> prototipos = new ArrayList();
                for(ArrayList<String> ar: todos){
                    for(Class inter: c.clasePorNombre(ar.get(0)).getInterfaces()){
                        if(inter.getSimpleName().equals("Cloneable")){
                          ArrayList<String> temp =  new ArrayList();
                          temp.add("Prototipo:"+ ar.toString() + "[90%]");
                          prototipos.add(temp);
                          interfaz.add(ar);
                        
                        }
                    }
                }
                
                p = prototipos.toArray();
                
                break;
                
            case "Adapter":
                
//                c.contenidoMetodo("BuilderDirector", "String");
                
                break;
                
            case "Composite":
                
                /**
                 * LA estructura del patron COMPOSITE es de dos o mas clases
                 * que extienden a otra, por lo tanto ya se tiene el
                 * primer 50%
                 */
                interfaz = new ArrayList();
                ArrayList<String> compuestos = new ArrayList();
                String componente = "";
                String compuesto = "";
                String cadena = "";
                int contador2 = 0;
                
                for(ArrayList<String> ar: dosMas){
                    contador = 0;
                    for(int i = 1; i < ar.size(); i++){
                        if(c.hayAsociacion(ar.get(i), ar.get(0))){
                            contador++;
                            cadena = "Componente:[" + ar.get(0) + "] Compuesto:[" 
                                    + ar.get(i) + "]";
                            componente = ar.get(0);
                            compuesto = ar.get(i);                                  
                                   
                        }
                        
                    }
                    //Solo debe una de todas las clases de la 
                    //Estructura tener asociacion con la super clase
                    if(contador == 1){
                        
                        interfaz.add(ar);
                        cadena += " Hojas:[";
                        for(String s: ar){
                           if(!s.equals(componente) && !s.equals(compuesto)) 
                               cadena += s + " ";
                        }
                        cadena += "]";
                        compuestos.add(cadena);
                        
                    }
                }
                
                p = compuestos.toArray();
                
                break;
                
            case "Decorator":
                
                ArrayList<String> decoradores = new ArrayList();
                interfaz = new ArrayList();
                String decorador = "";
                for(ArrayList<String> ar: dosMas){
                    decorador = "";
                    contador = 0;
                    for(int i = 1; i < ar.size(); i++){
                        if(c.hayAsociacion(ar.get(i), ar.get(0))){
                            contador++;
                            decorador = ar.get(i);
                        }
                        
                    }
                    
                    //Solo debe una de todas las clases de la 
                    //Estructura tener asociacion con la super clase
                    if(contador == 1){
                                               
                        for(ArrayList<String> ar2: todos){
                            if(ar2.get(0).equals(decorador)){
                                
                                ArrayList<String> paraInterfaz = new ArrayList(ar);
                                paraInterfaz.addAll(ar2);
                                interfaz.add(paraInterfaz);
                                decoradores.add("Componente:" + ar + " Decorador:" + ar2);
                            }               
                      }//Fin for 
                    }
                    
                }
                
                p = decoradores.toArray();
                
                break;
                
            case "Flyweight":
                ArrayList<String> flyweights = new ArrayList();
                ArrayList<String> paraInterfaz = new ArrayList();
                interfaz = new ArrayList();
                for(ArrayList<String> ar: todos){
                    for(Class s1: c.getClases()){
                        /*
                         * Las reglas son claras aqui, como es una estructura
                         * muy simple, se verifica por en la especificacion
                         * de la clase fabrica que algun metodo devuelva el
                         * flyweight,que el flyweight sea abstracto o interfaz y
                         * que la fabrica de flyweight tenga una referencia
                         * a los flyweights (Que debera ser un arreglo o lista)
                         */
                        if(c.algunMetodoDevuelve(s1.getSimpleName(), ar.get(0)) 
                                && c.esInterfaz(ar.get(0)) && c.tieneUn(s1.getSimpleName(), ar.get(0))
                                && !c.esInterfaz(s1.getSimpleName())) {
                            
                            paraInterfaz.add(s1.getSimpleName() + ar);
                            interfaz.add(paraInterfaz);
                            paraInterfaz = new ArrayList();
                            
                            flyweights.add("Fabrica:[" +s1.getSimpleName() + "] Flyweights:" + ar);
                            
                        }
                    }
                }
                
                p = flyweights.toArray();
                
                break;
                
                
            case "Proxy":
                
                //Para proxy virtual
                
                //Primera pasada
                HashSet<ArrayList<String>> posiblesProxys = new HashSet();
                interfaz = new ArrayList();
                for(ArrayList<String> ar: dosMas){
                    
                    for(int i = 1; i < ar.size(); i++){
                        for(int j = 2; j < ar.size(); j++){
                            
                            if(c.hayAsociacion(ar.get(i), ar.get(j))
                                    &&
                               c.clasePorNombre(ar.get(i)).getMethods().length <=
                               c.clasePorNombre(ar.get(j)).getMethods().length
                                    &&
                                !ar.get(i).equals(ar.get(j))){
                                
                                posiblesProxys.add(ar);
                                interfaz.add(ar);
                            }
                            else if(c.hayAsociacion(ar.get(j), ar.get(i))
                                    &&
                               c.clasePorNombre(ar.get(j)).getMethods().length <=
                               c.clasePorNombre(ar.get(i)).getMethods().length
                                    &&
                                !ar.get(i).equals(ar.get(j))){
                            
                                posiblesProxys.add(ar);
                            
                                if(!interfaz.contains(ar))
                                    interfaz.add(ar);
                            }
                            
                        }
                    }
                    
                }//Fin primer for
                
                /*
                 * Como en esta parte, solo se comprueba la estructura
                 * y el numero de metodos, tambien seria bueno que se 
                 * pudiera comprobar el nombre, por si contiene las palabras
                 * "proxy" o que entre las clases asociadas tengan palabras en
                 * comun, pero lo mejor sera desechar esa idea pues la
                 * nomenclatura de las clases son cuestiones del programador
                 */
                
                p = posiblesProxys.toArray();
                
                
                break;
                
            case "Chain of Responsability":
                StringBuilder sb = new StringBuilder();
                ArrayList<String> chains = new ArrayList();
                interfaz = new ArrayList();
                //1. Encontrar la estructura. Al igual que los demas
                /*Patrones en los que la estructura es la que dicta
                 * la mayoria del patron, hay que revisarla
                 */
                //No puede haber una cadena se es solo una subclase
                for(ArrayList<String> ar: dosMas){
                    
                    if(c.tieneUn(ar.get(0), ar.get(0))){
                        sb = new StringBuilder();
                        interfaz.add(ar);
                         sb.append("Manejador:[").append(ar.get(0)).append("] ManejadoresConcretos[");
                         
                         for(String s: ar){
                             if(!s.equals(ar.get(0))){
                                 sb.append(s).append(", ");
                             }
                         }
                         sb.deleteCharAt(sb.length() - 1);
                         sb.deleteCharAt(sb.length() - 1);
                         sb.append("]");
                         chains.add(sb.toString());
                    }
                }
                
                p = chains.toArray();
                
                break;
                 
                
            case "Command":
                
                HashSet<ArrayList<String>> comandos = new HashSet();
                for(ArrayList<String> ar: todos){
                    
                    for(Class cl1: c.getClases()){
                        int total1 = (ar.size() - 1);
                        contador = 0;
                        for(int i = 1; i < ar.size(); i++){
                            if(c.hayAsociacion(ar.get(i), cl1.getSimpleName())){
                                contador++;
                            }

                        }
                    
                        if(contador == total1){
                            comandos.add(ar);
                            
                        }
                    }
                    
                }
                
//                for(ArrayList<String> hs: comandos){
//                    System.out.println(hs);
//                }
                
                break;
                
            case "Iterator":
                ArrayList<String> iteradores = new ArrayList();
                interfaz = new ArrayList();
                paraInterfaz = new ArrayList();
                String pi = "";
                sb = new StringBuilder("Implementan a Iterator[");
                for(Class cl1: c.getClases()){
                    
                    for(Class in1: cl1.getInterfaces()){
                        if(in1.getSimpleName().equalsIgnoreCase("Iterator")){
                            pi += cl1.getSimpleName();
                            sb.append(cl1.getSimpleName()).append(",");
                           
                        } 
                    }
                }
                paraInterfaz.add(pi);
                interfaz.add(paraInterfaz);
                sb.deleteCharAt(sb.length()-1);
                sb.append("]");
                iteradores.add(sb.toString());
                
                p = iteradores.toArray();
                break;
                
            case "Template Method":
                
                interfaz = new ArrayList();
                HashSet<String> templates = new HashSet();
                /**
                 * El patron de diseño Template Method es una plantilla de 
                 * un algoritmo representada en la superclase de una estructura
                 * jerarquica por lo general se implementa teniendo un
                 * metodo plantilla en la super clase y metodos abstractos 
                 * en la subclase para que los implemente.
                 * 
                 * Aqui se buscan los que tienen en su superclase metodos
                 * que son abstractos y protegidos, pues es la unica 
                 * caracteristica que hace especial a este patron, de otra 
                 * manera seria una adaptacion del patron pero no utilizando
                 * GRASP
                 */
                for(ArrayList<String> ar: todos){
                    
                    for(Method m: c.clasePorNombre(ar.get(0)).getDeclaredMethods()){
                        if(Modifier.isAbstract(m.getModifiers()) && Modifier.isProtected(m.getModifiers())){
                            interfaz.add(ar);
                            templates.add("Template:"+ar);
                        }
                    }
                    
                    
                    /**
                     * No es necesario que sea de la siguiente forma, pero
                     * asi esta especificado:
                     * 
                     * Cada subclase debera tener todos los metodos de 
                     * su superclase, excepto el metodo plantilla, por lo
                     * tanto el numero de metodos de las subclases debera
                     * ser igual en todas y tambien debera ser menor que
                     * el de la superclase.
                     */
                    int totalMetodos = c.clasePorNombre(ar.get(1)).getDeclaredMethods().length;
                    boolean todosIgual = true;
                    for(int i = 1; i < ar.size(); i++){
                        if(c.clasePorNombre(ar.get(i)).getDeclaredMethods().length
                                != totalMetodos)
                            todosIgual = false;
                    }
                    
                    if((c.clasePorNombre(ar.get(0)).getDeclaredMethods().length
                            > totalMetodos) && todosIgual){
                        templates.add("Template:"+ar);
                    }
                }
                
                p = templates.toArray();
                
                break;
                
                
            case "Mediator":
                
                /**
                 * Hay una variante en la que el mediador no tiene por que
                 * ser especificamente una jerarquia de clases, pero en este
                 * caso nomas se programo para detectarlo cuando sea pues
                 * asi se especifico en el libro.
                 */
                contador = 0;
                HashSet<String> mediadores = new HashSet();
                interfaz = new ArrayList();
                paraInterfaz = new ArrayList();
                for(ArrayList<String> ar: todos){
                   
                    for(ArrayList<String> ar2: dosMas){
                        int tamano = ar2.size() - 1;
                        
                        if(!ar.equals(ar2)){
                        for(int i = 1; i < ar.size(); i++){
                            for(int j = 1; j < ar2.size(); j++){
                                
                                if(c.hayAsociacion(ar.get(i), ar2.get(j))){
                                    contador++;
                                }
                                
                                
                            }
                            
                            
                            if(tamano == contador){
                                
                                /**
                                 * Aqui tambien se debe verificar que el 
                                 * Colega abstracto tenga una referencia a 
                                 * el MediadorAbstracto, pero se omitio pues
                                 * pocas estructuras contaran con estas primeras
                                 * reglas
                                 */
                                paraInterfaz = new ArrayList(ar);
                                paraInterfaz.addAll(ar2);
                                interfaz.add(paraInterfaz);
                                mediadores.add("Mediador:"+ar + "Colegas:" + ar2);
                            }
                            
                            contador = 0;
                        }
                        
                        
                    }//fin if 
                        
                  }
                    
                    
                }
                
                p = mediadores.toArray();
                
                break;
              
                
            case "Observer":
                
                HashSet<String> observadores = new HashSet();
                interfaz = new ArrayList();
                paraInterfaz = new ArrayList();
                for(ArrayList<String> ar: todos){
                    
                    for(ArrayList<String> ar2: todos){
                        
                        if(!ar.equals(ar2)){
                            if(c.tieneUnGenerico(ar.get(0), ar2.get(0))){
                                paraInterfaz = new ArrayList(ar);
                                paraInterfaz.addAll(ar2);
                                interfaz.add(paraInterfaz);
                                observadores.add("Subjects:"+ar + "Observers:" + ar2);
                            }
                        }
                    }
                }
                
                p = observadores.toArray();
                break;
                
        }
        
       return p; 
    }
    
 
    
        public void generarEstructuras(){
        
        /**
         * Quita de la lista de clases que extiendan a Exception y las
         * que extiendan a Object
         */
        

        HashSet<String> simples = new HashSet();
        HashSet<ArrayList<String>> estructuras = new HashSet();
        for(Class cl: c.getClases()){
            ArrayList<String> a = new ArrayList();
            if(cl.getSuperclass() != null && c.existeClase(cl.getSuperclass().getSimpleName())){
                simples.add(cl.getSuperclass().getSimpleName());
                for(String a1: a)
                    simples.add(a1);
                
                a.add(0,cl.getSuperclass().getSimpleName());
                estructuras.add(a);
                a = new ArrayList();
            }
            else if(cl.getInterfaces().length != 0){
                for(Class interfaz: cl.getInterfaces()){
                   a.add(0,interfaz.getSimpleName());
                   simples.add(interfaz.getSimpleName());
                   if(!estructuras.contains(a) && c.existeClase(interfaz.getSimpleName())){
                       for(String a1: a)
                          simples.add(a1);
                       
                        estructuras.add(a);
                   }
                   a = new ArrayList();
                } 
            }  
        }
        
        
        for(ArrayList<String> al: estructuras){
            Class superclase = c.clasePorNombre(al.get(0));
            for(Class clase: c.getClases()){
                if(clase.getSuperclass() != null && !superclase.isInterface()){
                    if(clase.getSuperclass().getSimpleName().equalsIgnoreCase(superclase.getSimpleName())){
                        al.add(clase.getSimpleName());
                        simples.add(clase.getSimpleName());
                    } 
                }else{
                    //Puede ser una interfaz
                    for(Class interfaz: clase.getInterfaces()){
                        if(superclase.getSimpleName().equalsIgnoreCase(interfaz.getSimpleName())){
                            al.add(clase.getSimpleName());
                            simples.add(clase.getSimpleName());
                        }
                        
                    }
                    
                }
            }
            
            todos.add(al);
            if(al.size() > 2)
                dosMas.add(al);
            else if(al.size() == 2)
                soloUno.add(al);
        }

        
            HashSet<String> todasClases = new HashSet();
            for(Class classe: c.getClases()){
                if(!c.esInterfaz(classe.getSimpleName()))
                    todasClases.add(classe.getSimpleName());
            }
            todasClases.removeAll(simples);
            solitarias = todasClases;
    }

    public Clase getC() {
        return c;
    }
    

    
}
